﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Transactions;
using AB.ServiceDirectory.Commons.DataFilters;
using AB.ServiceDirectory.Entities;

namespace AB.ServiceDirectory.Dao
{
    [Serializable]
    public class ServicePremiseDao
    {
        [NonSerialized]
        private readonly ServicesDirectoryDataContext _context = DB.Context;

        /// <summary>
        /// Gets the list.
        /// </summary>
        /// <param name="filter">The filter.</param>
        /// <param name="sortType">Type of the sort.</param>
        /// <param name="startRowIndex">Start index of the row.</param>
        /// <param name="max">The max.</param>
        /// <returns></returns>
        public IQueryable<ServicePremise> GetList(ServicePremiseFilter filter, string sortType, int startRowIndex, int max)
        {
            var data = from sp in _context.ServicePremises
                       select sp;

            // 1.Filter
            if (filter != null)
            {
                data = GetListQuery(data, filter);
            }

            // 2. Sorting
            data = GetListSort(data, sortType);

            // 3. Limit the result
            data = data.Skip(startRowIndex).Take(max);

            // 4. Return Data
            return data;
        }

        /// <summary>
        /// Gets the list sort.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="sortType">Type of the sort.</param>
        /// <returns></returns>
        private static IQueryable<ServicePremise> GetListSort(IQueryable<ServicePremise> data, string sortType)
        {
            bool sortDecending = false;
            if (!string.IsNullOrEmpty(sortType))
            {
                string[] values = sortType.Split((' '));
                sortType = values[0];
                if (values.Length > 1)
                {
                    sortDecending = (values[1] == "DESC");
                }

                switch (sortType)
                {
                    case "LocationName":
                        data = sortDecending
                                   ? data.OrderByDescending(sp => sp.Premise.LocationName)
                                   : data.OrderBy(sp => sp.Premise.LocationName);
                        break;

                    case "AddressLine":
                        data = sortDecending
                                   ? data.OrderByDescending(sp => sp.Premise.Address.AddressLine)
                                   : data.OrderBy(sp => sp.Premise.Address.AddressLine);
                        break;

                    case "PhoneNumber":
                        data = sortDecending 
                                    ? data.OrderByDescending(sp => sp.Premise.PhoneNumber) 
                                    : data.OrderBy(sp => sp.Premise.PhoneNumber);
                        break;

                    case "ProjectCode":
                        data = sortDecending
                                   ? data.OrderByDescending(sp => sp.ProjectCode)
                                   : data.OrderBy(sp => sp.ProjectCode);
                        break;
                }
            }
            return data;
        }

        /// <summary>
        /// Gets the list query.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="filter">The filter.</param>
        /// <returns></returns>
        private static IQueryable<ServicePremise> GetListQuery(IQueryable<ServicePremise> data, ServicePremiseFilter filter)
        {
            // Filter by ServiceId
            if (filter.ServiceId > 0)
            {
                data = data.Where(sp => sp.ServiceId == filter.ServiceId);
            }
            // Filter by PremiseId
            else if (filter.PremiseId > 0)
            {
                data = data.Where(sp => sp.PremiseId == filter.PremiseId);
            }

            return data;
        }

        /// <summary>
        /// Gets the list count.
        /// </summary>
        /// <param name="filter">The filter.</param>
        /// <returns></returns>
        public int GetListCount(ServicePremiseFilter filter)
        {
            IQueryable<ServicePremise> data = from sp in _context.ServicePremises
                                              select sp;
            if (filter != null)
            {
                data = GetListQuery(data, filter);
            }
            return data.Count();
        }


        /// <summary>
        /// Edits the organization program.
        /// </summary>
        /// <param name="serviceId">The organization id.</param>
        /// <param name="list">The list.</param>
        /// <returns></returns>
        public bool EditInternalService(int serviceId, ICollection<InternalService> list)
        {
            try
            {
                using (var trans = new TransactionScope())
                {
                    var editedList = from i in _context.InternalServices
                                     where i.ServiceId == serviceId
                                     select i;

                    InternalService item = null;
                    foreach (var internalService in editedList)
                    {
                        item = list.FirstOrDefault(i => i.OtherServiceId == internalService.OtherServiceId);
                        if (item == null)
                        {
                            _context.InternalServices.DeleteOnSubmit(internalService);
                            _context.SubmitChanges();
                            continue;
                        }

                        list.Remove(item);
                    }

                    _context.InternalServices.InsertAllOnSubmit(list);
                    _context.SubmitChanges();
                    trans.Complete();
                }
            }
            catch (SqlException ex)
            {
                Log.GetLog(this).Error(ex);
                return false;
            }
            return false;
        }


        /// <summary>
        /// Determines whether [is name exists] [the specified service name].
        /// </summary>
        /// <param name="serviceName">Name of the service.</param>
        /// <returns>
        ///   <c>true</c> if [is name exists] [the specified service name]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsNameExists(string serviceName)
        {
            var service = _context.Services.FirstOrDefault(s => s.ServiceName.Equals(serviceName));
            return service != null;
        }

        /// <summary>
        /// Gets the internal service.
        /// </summary>
        /// <param name="serviceId">The service id.</param>
        /// <returns></returns>
        public IQueryable<InternalService> GetInternalService(int serviceId)
        {
            var internalServices = from i in _context.InternalServices
                                   where i.ServiceId == serviceId
                                   select i;
            return internalServices;
        }

        public bool AssociateServiceAndPremise(ServicePremise servicePremise)
        {
            try
            {
                _context.ServicePremises.InsertOnSubmit(servicePremise);
                _context.SubmitChanges();
                return true;
            }
            catch (SqlException ex)
            {
                Log.GetLog(this).Error(ex);
                return false;
            }
        }

        public bool RemoveAssociatedServicePremise(ServicePremise servicePremise)
        {
            try
            {
                var deletedServicePremise = (from s in _context.ServicePremises
                                             where
                                                 s.ServiceId == servicePremise.ServiceId &&
                                                 s.PremiseId == servicePremise.PremiseId
                                             select s).FirstOrDefault();
                if (deletedServicePremise != null)
                {
                    _context.ServicePremises.DeleteOnSubmit(deletedServicePremise);
                    _context.SubmitChanges();
                    return true;
                }
            }
            catch (SqlException ex)
            {
                Log.GetLog(this).Error(ex);
                return false;
            }

            return false;
        }
    }
}
